package main

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"io"
	"net"
)

var users map[string]*Connect

var serverMassageHanlder ServerMassageHanlder = ServerMassageHanlder{}

func main() {

	//监听
	listener, listenerErr := net.Listen("tcp", "127.0.0.1:80")

	if listenerErr == nil {
		users = make(map[string]*Connect, 1000)
		fmt.Println("listener start ....")
	} else {

		fmt.Println("listener error ....", listenerErr)
	}

	for {

		conn, acceptErr := listener.Accept()

		if acceptErr == nil {

			go func(conn net.Conn) {

				id := UniqueId()
				connect := &Connect{conn: conn, id: UniqueId(), isActive: true}
				users[id] = connect
				serverMassageHanlder.onAccept(connect, conn.RemoteAddr())

				massageBody := make([] byte, 1024*8)

				n, readErr := connect.conn.Read(massageBody)

				if readErr == nil {

					serverMassageHanlder.onMassage(connect, string(massageBody[0:n]))

				} else if readErr != nil {

					switch readErr.(type) {

					case *net.OpError:

						serverMassageHanlder.onDisconnect(connect, connect.conn.RemoteAddr())
					}
				}

			}(conn)
		} else {

			fmt.Println("acceptErr : ", acceptErr)
		}
	}

}

type ServerMassageHanlder struct {
}

func (ServerMassageHanlder) onAccept(con *Connect, addr net.Addr) {

	fmt.Println("新来一个客户端连接 : ", addr.String())

	user := users[con.id]

	if user != nil {

		fmt.Println("用户上线了", con.id)
	}
}

func (ServerMassageHanlder) onMassage(con *Connect, mag string) {

	fmt.Println("收到消息 :", mag)

	go func() {

		for _, connect := range users {

			serverMassageHanlder.write(connect, mag)
		}

	}()
}

func (ServerMassageHanlder) onDisconnect(con *Connect, addr net.Addr) {

	user := users[con.id]

	fmt.Println("远程客户断开连接 : ", addr.String(),con.id,user)


	//if user != nil {

		//delete(users, con.id)

		for _, connect := range users {

			serverMassageHanlder.write(connect, "用户 : "+con.id+"----下线咯")
		}

		fmt.Println("用户下线 :", con.id)

	//}
}

func (ServerMassageHanlder) onWriteComplete(con *Connect) {

	fmt.Println("发送数据完成:", con.id)
}

func (ServerMassageHanlder) write(con *Connect, msg string) {

	con.conn.Write([]byte(msg))
}

type Connect struct {
	conn net.Conn

	id string

	isActive bool
}

//生成32位md5字串
func GetMd5String(s string) string {
	h := md5.New()
	h.Write([]byte(s))
	return hex.EncodeToString(h.Sum(nil))
}

//生成Guid字串
func UniqueId() string {
	b := make([]byte, 48)

	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return ""
	}
	return GetMd5String(base64.URLEncoding.EncodeToString(b))

}
